/** * This file is part of pwt. * * pwt is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser * General Public License as published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * pwt is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License along with pwt. If not, * see <http://www.gnu.org/licenses/>. */ package fr.putnami.gwt.gradle.task; import com.google.common.base.Strings; import com.google.common.base.Throwables; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Lists; import org.gradle.api.Project; import org.gradle.api.internal.ConventionMapping; import org.gradle.api.internal.IConventionAware; import org.gradle.api.plugins.JavaPlugin; import org.gradle.api.plugins.JavaPluginConvention; import org.gradle.api.plugins.WarPluginConvention; import org.gradle.api.tasks.Input; import org.gradle.api.tasks.SourceSet; import org.gradle.api.tasks.TaskAction; import java.io.File; import java.io.IOException; import java.util.List; import java.util.Map; import java.util.concurrent.Callable; import java.util.concurrent.Semaphore; import fr.putnami.gwt.gradle.action.JavaAction; import fr.putnami.gwt.gradle.action.JavaAction.ProcessLogger; import fr.putnami.gwt.gradle.extension.DevOption; import fr.putnami.gwt.gradle.extension.PutnamiExtension; import fr.putnami.gwt.gradle.helper.CodeServerBuilder; import fr.putnami.gwt.gradle.helper.JettyServerBuilder; import fr.putnami.gwt.gradle.util.ResourceUtils; public class GwtDevTask extends AbstractTask { public static final String NAME = "gwtDev"; private List<String> modules = Lists.newArrayList(); private File jettyConf; public GwtDevTask() { setDescription("Run DevMode"); dependsOn(JavaPlugin.COMPILE_JAVA_TASK_NAME, JavaPlugin.PROCESS_RESOURCES_TASK_NAME); } @TaskAction public void exec() throws Exception { PutnamiExtension putnami = getProject().getExtensions().getByType(PutnamiExtension.class); DevOption sdmOption = putnami.getDev(); createWarExploded(sdmOption); ResourceUtils.ensureDir(sdmOption.getWar()); ResourceUtils.ensureDir(sdmOption.getWorkDir()); try { this.jettyConf = new File(getProject().getBuildDir(), "putnami/conf/jetty-run-conf.xml"); Map<String, String> model = new ImmutableMap.Builder<String, String>() .put("__WAR_FILE__", sdmOption.getWar().getAbsolutePath()) .build(); ResourceUtils.copy("/stub.jetty-conf.xml", jettyConf, model); } catch (IOException e) { Throwables.propagate(e); } JavaAction sdm = execSdm(); if (sdm.isAlive()) { JavaAction jetty = execJetty(); jetty.join(); } } private void createWarExploded(DevOption sdmOption) throws IOException { WarPluginConvention warConvention = getProject().getConvention().getPlugin(WarPluginConvention.class); JavaPluginConvention javaConvention = getProject().getConvention().getPlugin(JavaPluginConvention.class); File warDir = sdmOption.getWar(); ResourceUtils.copyDirectory(warConvention.getWebAppDir(), warDir); if (Boolean.TRUE.equals(sdmOption.getNoServer())) { File webInfDir = ResourceUtils.ensureDir(new File(warDir, "WEB-INF")); ResourceUtils.deleteDirectory(webInfDir); } else { SourceSet mainSourceSet = javaConvention.getSourceSets().getByName("main"); File classesDir = ResourceUtils.ensureDir(new File(warDir, "WEB-INF/classes")); for (File file : mainSourceSet.getResources().getSrcDirs()) { ResourceUtils.copyDirectory(file, classesDir); } ResourceUtils.copyDirectory(mainSourceSet.getOutput().getClassesDir(), classesDir); for (File file : mainSourceSet.getOutput().getFiles()) { if (file.exists() && file.isFile()) { ResourceUtils.copy(file, new File(classesDir, file.getName())); } } File libDir = ResourceUtils.ensureDir(new File(warDir, "WEB-INF/lib")); for (File file : mainSourceSet.getRuntimeClasspath()) { if (file.exists() && file.isFile()) { ResourceUtils.copy(file, new File(libDir, file.getName())); } } } } private JavaAction execJetty() { PutnamiExtension putnami = getProject().getExtensions().getByType(PutnamiExtension.class); JettyServerBuilder jettyBuilder = new JettyServerBuilder(); jettyBuilder.configure(getProject(), putnami.getJetty(), jettyConf); JavaAction jetty = jettyBuilder.buildJavaAction(); jetty.execute(this); return jetty; } private JavaAction execSdm() { PutnamiExtension putnami = getProject().getExtensions().getByType(PutnamiExtension.class); DevOption devOption = putnami.getDev(); if (!Strings.isNullOrEmpty(putnami.getSourceLevel()) && Strings.isNullOrEmpty(devOption.getSourceLevel())) { devOption.setSourceLevel(putnami.getSourceLevel()); } CodeServerBuilder sdmBuilder = new CodeServerBuilder(); if (!putnami.getGwtVersion().startsWith("2.6")) { sdmBuilder.addArg("-launcherDir", devOption.getWar()); } sdmBuilder.configure(getProject(), putnami.getDev(), getModules()); final JavaAction sdmAction = sdmBuilder.buildJavaAction(); final Semaphore lock = new Semaphore(1); sdmAction.setInfoLogger(new ProcessLogger() { private boolean started = false; @Override protected void printLine(String line) { super.printLine(line); if (line.contains("The code server is ready")) { this.started = true; lock.release(); } if (!started && line.contains("[ERROR]")) { sdmAction.kill(); lock.release(); } } }); lock.acquireUninterruptibly(); sdmAction.execute(this); lock.acquireUninterruptibly(); return sdmAction; } public void configureCodeServer(final Project project, final PutnamiExtension extention) { final DevOption options = extention.getDev(); options.init(project); ConventionMapping convention = ((IConventionAware) this).getConventionMapping(); convention.map("modules", new Callable<List<String>>() { @Override public List<String> call() throws Exception { return extention.getModule(); } }); } @Input public List<String> getModules() { return modules; } }